// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <gtest/gtest.h>
#include <climits>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cantor/parser/parser.h>

int main(int argc, char *argv[]) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

namespace cantor::parser {

    TEST(test_parser, begin_txn) {
        cantor::parser::SqlParser parser;
        std::string sql = "TXN START;";
        parser.parse(sql);
        if (parser.error != cantor::parser::SUCCESS) {
            std::cout << parser.result.size() << " error:" << parser.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt = (StmtNode *) parser.result[0];
        ASSERT_EQ(stmt->stmt_type, cantor::pb::ast::STMT_START_TRANSACTION)<<static_cast<int>(stmt->stmt_type)<<" "<<static_cast<int>(cantor::pb::ast::STMT_TYPE_NAME);
        StartTxnStmt* start_txn = (StartTxnStmt *) stmt;
        std::cout<<start_txn->to_json()<<std::endl;
        //////////////////////
        cantor::parser::SqlParser parser2;
        std::string sql2 = "TXN START work;";
        parser2.parse(sql2);
        if (parser2.error != cantor::parser::SUCCESS) {
            std::cout << parser2.result.size() << " error:" << parser2.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt2 = (StmtNode *) parser2.result[0];
        ASSERT_EQ(stmt2->stmt_type, cantor::pb::ast::STMT_START_TRANSACTION);
        StartTxnStmt* start_txn2 = (StartTxnStmt *) stmt2;
        std::cout<<start_txn2->to_json()<<std::endl;
        //////////////////////
        cantor::parser::SqlParser parser3;
        std::string sql3 = "txn start transaction;";
        parser3.parse(sql3);
        if (parser3.error != cantor::parser::SUCCESS) {
            std::cout << parser3.result.size() << " error:" << parser3.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt3 = (StmtNode *) parser3.result[0];
        ASSERT_EQ(stmt3->stmt_type, cantor::pb::ast::STMT_START_TRANSACTION);
        StartTxnStmt* start_txn3 = (StartTxnStmt *) stmt3;
        std::cout<<start_txn3->to_json()<<std::endl;
    }

    TEST(test_parser, commit_txn) {
        cantor::parser::SqlParser parser;
        std::string sql = "txn COMMIT;";
        parser.parse(sql);
        if (parser.error != cantor::parser::SUCCESS) {
            std::cout << parser.result.size() << " error:" << parser.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt = (StmtNode *) parser.result[0];
        ASSERT_EQ(stmt->stmt_type, cantor::pb::ast::STMT_COMMIT_TRANSACTION);
        CommitTxnStmt* commit_txn = (CommitTxnStmt *) stmt;
        std::cout<<commit_txn->to_json()<<std::endl;

        //////////////////////
        cantor::parser::SqlParser parser2;
        std::string sql2 = "txn COMMIT work;";
        parser2.parse(sql2);
        if (parser2.error != cantor::parser::SUCCESS) {
            std::cout << parser2.result.size() << " error:" << parser2.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt2 = (StmtNode *) parser2.result[0];
        ASSERT_EQ(stmt2->stmt_type, cantor::pb::ast::STMT_COMMIT_TRANSACTION);
        CommitTxnStmt* commit_txn2 = (CommitTxnStmt *) stmt2;
        std::cout<<commit_txn2->to_json()<<std::endl;
    }

    TEST(test_parser, rollback_txn) {
        cantor::parser::SqlParser parser;
        std::string sql = "txn rollback;";
        parser.parse(sql);
        if (parser.error != cantor::parser::SUCCESS) {
            std::cout << parser.result.size() << " error:" << parser.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt = (StmtNode *) parser.result[0];
        ASSERT_EQ(stmt->stmt_type, cantor::pb::ast::STMT_ROLLBACK_TRANSACTION);
        RollbackTxnStmt* rollback_txn = (RollbackTxnStmt *) stmt;
        std::cout<<rollback_txn->to_json()<<std::endl;
        //////////////////////
        cantor::parser::SqlParser parser2;
        std::string sql2 = "txn rollback work;";
        parser2.parse(sql2);
        if (parser2.error != cantor::parser::SUCCESS) {
            std::cout << parser2.result.size() << " error:" << parser2.syntax_err_str << std::endl;
            return;
        }
        StmtNode *stmt2 = (StmtNode *) parser2.result[0];
        ASSERT_EQ(stmt2->stmt_type, cantor::pb::ast::STMT_ROLLBACK_TRANSACTION);
        RollbackTxnStmt* rollback_txn2 = (RollbackTxnStmt *) stmt2;
        std::cout<<rollback_txn2->to_json()<<std::endl;
    }
}  // namespace cantor::parser
